package cn.itcast.account.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.itcast.account.entity.AccountFreeze;
import cn.itcast.account.mapper.AccountFreezeMapper;
import cn.itcast.account.mapper.AccountMapper;
import cn.itcast.account.service.AccountFreezeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author Xiao
 * @version 1.0
 * @description
 * @date 2021/11/16
 */
@Service
public class AccountFreezeServiceImpl
        extends ServiceImpl<AccountFreezeMapper, AccountFreeze>
        implements AccountFreezeService {
    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private AccountFreezeMapper accountFreezeMapper;
    /**
     * try：资源检查和预留
     * @param userId
     * @param money
     */
    @Override
    public void deduct(String userId, int money) {
        String xid = RootContext.getXID();  //获取全局事务id
        //根据xid查询account_freeze ，如果已经存在则证明Cancel已经执行，拒绝执行try业务
        AccountFreeze accountFreeze = this.getById(xid);
        if (ObjectUtil.isNotEmpty(accountFreeze)) {
            return;
        }
        //扣减account表可用金额
        accountMapper.deduct(userId, money);
        //记录冻结金额和事务状态到account_freeze表
        accountFreeze = new AccountFreeze();
        accountFreeze.setXid(xid);
        accountFreeze.setUserId(userId);
        accountFreeze.setFreezeMoney(money);
        accountFreeze.setState(AccountFreeze.State.TRY);
        this.save(accountFreeze);
    }

    /**
     * confirm：业务执行和提交
     * @param context
     * @return
     */
    @Override
    public Boolean confirm(BusinessActionContext context) {
        //根据xid删除account_freeze表的冻结记录
        String xid = context.getXid();
        return this.removeById(xid);
    }

    /**
     * cancel：预留资源的释放
     * @param context
     * @return
     */
    @Override
    public Boolean cancel(BusinessActionContext context) {
        //根据xid查询account_freeze，如果为null则说明try还没做，需要空回滚
        AccountFreeze accountFreeze = this.getById(context.getXid());
        if (ObjectUtil.isEmpty(accountFreeze)) {
            accountFreeze = new AccountFreeze();
            accountFreeze.setXid(context.getXid());
            accountFreeze.setUserId(context.getActionContext("userId").toString());
            accountFreeze.setFreezeMoney(0);
            accountFreeze.setState(AccountFreeze.State.CANCEL);
            return this.save(accountFreeze);
        }
        //幂等性处理
        if (ObjectUtil.equals(accountFreeze.getState(), AccountFreeze.State.CANCEL)) {
            //已经处理过一次cancel，无需重复处理
            return true;
        }
        //修改account表，恢复可用金额
        accountMapper.refund(accountFreeze.getUserId(), accountFreeze.getFreezeMoney());
        //修改account_freeze表，冻结金额为0，state为2
        accountFreeze.setFreezeMoney(0);
        accountFreeze.setState(AccountFreeze.State.CANCEL);
        return this.updateById(accountFreeze);
    }
}
